﻿namespace TomatoBreak.Web
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;

    using DataAccess;
    using DomainObjects;
    using Infrastructure;

    public class TasksController : AuthenticatedController
    {
        private readonly IRepository<Task> repository;

        public TasksController(IRepository<Task> repository)
        {
            if (repository == null)
            {
                throw new ArgumentNullException("repository");
            }

            this.repository = repository;
        }

        public ActionResult Index()
        {
            var tasks = GetTasks(() => repository.FindAll(t => t.CompletedAt == null && (t.DueAt == null || t.DueAt >= Clock.UtcNow())));

            return Json(tasks, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Create(TaskModel createModel)
        {
            if (createModel == null)
            {
                throw new ArgumentNullException("createModel");
            }

            if (!ModelState.IsValid)
            {
                return JsonModelStateErrors();
            }

            var task = createModel.Create(CurrentUser);

            repository.Add(task);

            return JsonCreated(Map(task));
        }

        public ActionResult Update(Guid id, TaskModel updateModel)
        {
            if (updateModel == null)
            {
                throw new ArgumentNullException("updateModel");
            }

            if (!ModelState.IsValid)
            {
                return JsonModelStateErrors();
            }

            var task = repository.FindOne(t => t.Id == id && t.User.Id == CurrentUser.Id && !t.Archived);

            if (task == null)
            {
                return HttpNotFound();
            }

            updateModel.CopyTo(task);

            repository.Update(task);

            return HttpOk();
        }

        private static object Map(Task task)
        {
            return new
                    {
                        task.Id,
                        task.Name,
                        task.Planned,
                        task.Notes,
                        task.Estimation,
                        task.CreatedAt,
                        task.DueAt,
                        task.CompletedAt
                    };
        }

        private IEnumerable<object> GetTasks(Func<IQueryable<Task>> query)
        {
            return query().Where(t => t.User.Id == CurrentUser.Id && !t.Archived)
                          .OrderByDescending(t => t.CreatedAt)
                          .Select(Map)
                          .ToList();
        }
    }
}